/**
 * 
 */
package Lamport;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.Queue;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 
/**
 * @author conloguern3
 *
 */

public class LamportProtocol {
	//	private LamportClient lc = new LamportClient();

	/* Elements of array:
	 * 	[0] message timestamp
	 * 	[1] message type
	 * 	[2] hostname of sender
	 */


	@SuppressWarnings("unused")
	public String processInput(String theInput) throws IOException {
		InetAddress localaddr = InetAddress.getLocalHost();
		String tempTimerString = null;
		int tempTimerInt = 0;
		String theOutput = null;
		boolean match = false;
		boolean cond_1 = false;
		boolean cond_2 = false;
		Queue<String[]> queue = new LinkedList<String[]>();

		String scanned = null;
		String[] list = new String[10];
		String[] tempList = new String[10];
		String[] test;

		//Parse through the hosts file, get all the names and put into array
		int hostIndex = 0;


		InputStream hostsURL = getClass().getResourceAsStream("hosts");	
		
		
		//	DataInputStream dis = new DataInputStream(infile);
			BufferedReader br = null;
			try {
				br = new BufferedReader(new InputStreamReader(hostsURL, "UTF-8"));
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			try{
				while((scanned = br.readLine()) != null){
					list[hostIndex] = scanned;
					hostIndex++;
				}
			} catch(IOException e1){
				e1.printStackTrace();
			}

		tempList = list;



		String[] inputArray = theInput.split(" ");
		//	System.out.println(inputArray[1]);

		if(inputArray.length < 3){
			theOutput = "Input is Null";
		}
		else{

			tempTimerString = inputArray[0];
			tempTimerInt = Integer.parseInt(tempTimerString.trim()); //Convert timestamp to integer
			String tempTimerStringTest = null;
			int tempTimerIntTest = 0;
			int queueSize = 0;
			int timeStamp_TM = 0;



			/*
			 * Test if the message is a request
			 * if it is a request it will then check to see if it has the lowest timestamp
			 * if not, it will add it to the queue of messages.
			 * 
			 */
			if(inputArray[1].equalsIgnoreCase("Req")){
				
				/*
				 * Check to see if current program has the resource
				 * If not, condition 2 is true
				 */
				if(GUI.controlResource == false){
					cond_2 = true;
				}
				else{
					theOutput = (GUI.lamportTimer + " RinUse " + localaddr.getHostName());
				}

				//Compare the timestamp of the new message with whats currently on the queue.
				if(queue.peek() != null){
				test = queue.peek();
				tempTimerStringTest = test[0];
				tempTimerIntTest = Integer.parseInt(tempTimerStringTest.trim());
				}
				else{
					cond_1 = true;
				}
				//Test condition below
				if(timeStamp_TM < tempTimerIntTest){
					//Timestamp TM is lower than the tested item, so condition 1 is satisfied.
					cond_1 = true;
				}else{
					queue.add(inputArray);
				}
				/*
				 * Function below increases the Timestamp and Responds with an ack
				 * 					
				 */
				if(cond_1 && cond_2){
					System.out.println(theInput);
					System.out.println(tempTimerInt);
					tempTimerInt = tempTimerInt + 2; // Increment timestamp
					GUI.setTimer(tempTimerInt);
					String senderHostName = inputArray[2];
					System.out.println(senderHostName);
					GUI.changeNode(senderHostName);
					GUI.updateHosts();
					theOutput = (GUI.lamportTimer + " Ack " + localaddr.getHostName());
				}
			}
			
			
			
			else if (inputArray[1].equalsIgnoreCase("Ack")) {
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2; // Increment timestamp
				GUI.setTimer(tempTimerInt);
				theOutput = ("Acknowledgement Received " + localaddr.getHostName());	
			}
			
			
			else if (inputArray[1].equalsIgnoreCase("Rel")){
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2; // Increment timestamp
				GUI.setTimer(tempTimerInt);
				String senderHostName = inputArray[2];
				System.out.println(senderHostName);
				GUI.changeNode(senderHostName);
				theOutput = (GUI.lamportTimer + " Ack-Rel " + localaddr.getHostName());

			}
			else if (inputArray[1].equalsIgnoreCase("Ack-Rel")){
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2;
				GUI.setTimer(tempTimerInt);
				theOutput = ("Release Acknowlegement Received");
			}
			else if(inputArray[1].equalsIgnoreCase("RinUse")){
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2;
				GUI.setTimer(tempTimerInt);
				theOutput = ("Resource In Use by: " + inputArray[2]);
			}
			else if(inputArray[1].equalsIgnoreCase("Auto")){
				System.out.println(theInput);
				tempTimerInt = tempTimerInt + 2;
				GUI.setTimer(tempTimerInt);
				GUI.setAutomaticMode();
				theOutput = (GUI.lamportTimer + " Ack-Auto " + localaddr.getHostName());
			}
			else if(inputArray[1].equalsIgnoreCase("Ack-Auto")){
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2;
				GUI.setTimer(tempTimerInt);
				theOutput = (GUI.lamportTimer + " Auto Acknowlegement Received");
			}
			
			else if (inputArray[1].equalsIgnoreCase("Quit")){
				System.out.println(theInput);
				System.out.println(tempTimerInt);
				tempTimerInt = tempTimerInt + 2;
				GUI.setTimer(tempTimerInt);
				theOutput = ("Quit");
			}

			else {
				System.out.println(theInput);
				theOutput = (GUI.lamportTimer + " Message Format Not Recognized. " + localaddr.getHostName());
			}
		}

		return theOutput;
	}
}
